#ifndef CON_QUEUE_H_INCLUDED
#define CON_QUEUE_H_INCLUDED

#include <queue>

#include <boost/thread.hpp>
#include <boost/noncopyable.hpp>

namespace Common {

/**
 *  
 */
template <typename T>
class ConcurrentQueue : boost::noncopyable {
public	:
	ConcurrentQueue() : 
		m_queue(), 
		m_mutex(), 
		m_condition(), 
		m_nonblockState(false) 
	{ 
	}

	~ConcurrentQueue() 
		{ setUnblockState(true); }
	
	/** Push data to queue
	 * 	 
	 */
	inline void push(T data)
	{
		boost::mutex::scoped_lock lock(m_mutex);
		m_queue.push(data);
		lock.unlock();	
		m_condition.notify_one();
	}
	
	/** Pop data from queue/ If there is no data wait for ne wprtion fo specified timeout
	 * 
	 *  @return
	 */
	bool pop(T & data) 
	{
		boost::mutex::scoped_lock guard(m_mutex);
		
		while (m_queue.empty()) {
			if (!m_nonblockState)
				m_condition.wait(guard);
		}

		if (!m_queue.empty()) {	
			data = m_queue.front();
			m_queue.pop();
			return true;
		} 
		return false;
	}

	inline void setUnblockState(bool state) 
	{
		boost::mutex::scoped_lock lock(m_mutex);
		m_nonblockState = state;
		lock.unlock();	
		m_condition.notify_one();
	}
	
	inline bool timedPop(T &data, std::size_t deadline)
	{
		boost::mutex::scoped_lock lock(m_mutex);		
		return false;
	}

	inline std::size_t size() const 
	{
		boost::mutex::scoped_lock lock(m_mutex);		
		return m_queue.size();
	}
	
private :
	std::queue<T> m_queue;	
	boost::mutex mutable m_mutex;
    boost::condition_variable m_condition;
	bool m_nonblockState;

};

} // namespace Common

#endif
